function SOHotkeyConfig(platformKeysId, localeKeysId) {
	this.platformKeys = {};
	this.localeKeys = {};
	this.vkNames = [];
	
	this._platformKeysId = platformKeysId;
	this._localeKeysId = localeKeysId;
}

SOHotkeyConfig.prototype = {
	init: function(hotkeyTextbox, hotkeyPref) {
		this.localeKeys = document.getElementById(this._localeKeysId);
		
		var platformKeys = document.getElementById(this._platformKeysId);
		this.platformKeys.shift   = platformKeys.getString("VK_SHIFT");
		this.platformKeys.meta    = platformKeys.getString("VK_META");
		this.platformKeys.alt     = platformKeys.getString("VK_ALT");
		this.platformKeys.control = platformKeys.getString("VK_CONTROL");
		this.platformKeys.sep     = platformKeys.getString("MODIFIER_SEPARATOR");

		var pref = Components.classes['@mozilla.org/preferences-service;1']
		      	.getService(Components.interfaces.nsIPrefService)
				.getBranch("ui.key.");

		switch (pref.getIntPref("accelKey")) {
		    case 17:
		      this.platformKeys.accel = this.platformKeys.control;
		      break;
		    case 18: 
		      this.platformKeys.accel = this.platformKeys.alt;
		      break;
		    case 224:
		      this.platformKeys.accel = this.platformKeys.meta;
		      break;
		    default:
		      this.platformKeys.accel = (window.navigator.platform.search("Mac") == 0 ?
		                                 this.platformKeys.meta : this.platformKeys.control);
		}		
		
		for (var property in KeyEvent) {
			this.vkNames[KeyEvent[property]] = property.replace("DOM_","");
		}
		this.vkNames[8] = "VK_BACK";
		
		// init the textbox
		var param = hotkeyPref.split(/,/);
		hotkeyTextbox.value = this.getPrintableKeyName(param[2], param[0], param[1]);
		hotkeyTextbox.initialValue = hotkeyTextbox.pref = hotkeyPref;
	},
	
	recognize: function(e) {
	    e.preventDefault();
	    e.stopPropagation();

	    var modifiers = [];
	    if(e.altKey)   modifiers.push("alt");
	    if(e.ctrlKey)  modifiers.push("control");
	    if(e.metaKey)  modifiers.push("meta");
	    if(e.shiftKey) modifiers.push("shift");

	    modifiers = modifiers.join(" ");

	    var key = "";
	    var keycode = "";
	    if(e.charCode) {
	      key = String.fromCharCode(e.charCode).toUpperCase();
	    }
	    else { 
	      keycode = this.vkNames[e.keyCode];
	      if(!keycode) return;
	    }

	    var val = this.getPrintableKeyName(modifiers, key, keycode);
	    if (val) {
	      e.target.value = val;
	      e.target.pref = key + "," + keycode + "," + modifiers;
	    }

	  },

	  revert: function(e) {
	    var target = e.target.previousSibling;
	    var param = target.initialValue.split(/,/);
	    target.value = this.getPrintableKeyName(param[2], param[0], param[1]);
	    target.pref  = param[0] + "," + param[1] + "," + param[2];
	  },
	
  getPrintableKeyName: function(modifiers, key, keycode) {
    if(modifiers == "shift,alt,control,accel" && keycode == "VK_SCROLL_LOCK") return "";

    if (!modifiers && !keycode)
      return "";

    var val = "";
    if(modifiers) {
      val = modifiers.replace(/^[\s,]+|[\s,]+$/g,"").split(/[\s,]+/g).join(this.platformKeys.sep);
    }

    var   mod = ["alt", "shift", "control", "meta", "accel"];
    for (var i in mod) {
      val = val.replace(mod[i], this.platformKeys[mod[i]]);
    }

    if (val)
      val += this.platformKeys.sep;

    if(key) {
      val += key;
    }
    if(keycode) {
      try {
        val += this.localeKeys.getString(keycode);
      }
      catch(e) {
        val += keycode;
      }
    }

    return val;
  }
}